package com.hrsaas.ext.spider.core.url;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.hrsaas.ext.spider.util.Assert;

/**
 * <p>
 * 功能：请求参数处理类
 * <p>
 * 
 * @author wangxiaoliang@kanzhun.com
 *
 *         2018年8月1日
 */
public final class ParsedParameters extends Parameters implements Iterable<ParametersElement> {
	private final ParametersElement[] elements;
	private final ParametersDelimiter delimiter;

	public ParsedParameters(ParametersElement... elements) {
		this(ParametersDelimiter.AMPERSAND, elements);
	}

	public ParsedParameters(ParametersDelimiter delimiter, ParametersElement... elements) {
		Assert.notNull("elements", elements);
		Assert.notNull("delimiter", delimiter);
		Assert.noNullElements("elements", elements);
		this.delimiter = delimiter;
		this.elements = new ParametersElement[elements.length];
		System.arraycopy(elements, 0, this.elements, 0, elements.length);
	}

	public ParametersDelimiter getDelimiter() {
		return delimiter;
	}

	public String getFirst(String param) {
		for (ParametersElement p : elements) {
			if (p.getKey().equals(param)) {
				return p.getValue();
			}
		}
		return null;
	}

	public List<String> getAll(String param) {
		List<String> result = new ArrayList<>(elements.length);
		for (ParametersElement p : elements) {
			if (p.getKey().equals(param)) {
				result.add(p.getValue());
			}
		}
		return result;
	}

	public static Parameters parse(String queryString) {
		Assert.notNull("queryString", queryString);
		if (queryString == null || queryString.length() == 0) {
			return null;
		}
		String[] parts = null;
		ParametersDelimiter delim = ParametersDelimiter.AMPERSAND;
		if (queryString.indexOf(ParametersDelimiter.AMPERSAND.charValue()) >= 0) {
			parts = queryString.split("\\" + ParametersDelimiter.SEMICOLON.charValue());
			delim = ParametersDelimiter.AMPERSAND;
		} else if (queryString.indexOf(ParametersDelimiter.SEMICOLON.charValue()) >= 0) {
			parts = queryString.split("\\" + ParametersDelimiter.SEMICOLON.charValue());
			delim = ParametersDelimiter.SEMICOLON;
		} else {
			if (queryString.startsWith("=") && queryString.length() > 1) {
				ParsedParameters result = new ParsedParameters(ParametersDelimiter.AMPERSAND,
						new ParametersElement(null, queryString.substring(1)));
				return result;
			} else if (queryString.startsWith("?=") && queryString.length() > 2) {
				return new ParsedParameters(ParametersDelimiter.AMPERSAND,
						new ParametersElement(null, queryString.substring(2)));
			} else {
				String[] keyValue = queryString.split("=", 2);
				if (keyValue.length == 1) {
					return new ParsedParameters(ParametersDelimiter.AMPERSAND,
							new ParametersElement(keyValue[0], null));
				}
				return new ParsedParameters(ParametersDelimiter.AMPERSAND,
						new ParametersElement(keyValue[0], keyValue[1]));
			}
		}
		ParametersElement[] els = new ParametersElement[parts.length];
		for (int i = 0; i < parts.length; i++) {
			String part = parts[i];
			els[i] = ParametersElement.parse(part);
		}
		ParsedParameters result = new ParsedParameters(delim, els);
		if (!result.unescaped().equals('?' + queryString)) {
			return new Parameters(queryString);
		}
		return result;
	}

	public ParametersElement[] getElements() {
		ParametersElement[] result = new ParametersElement[elements.length];
		System.arraycopy(elements, 0, result, 0, elements.length);
		return result;
	}

	public int size() {
		return elements.length;
	}

	public String unescaped() {
		String s = toString(delimiter);
		return URLBuilder.unescape(s);
	}

	@Override
	public String toString() {
		return toString(delimiter);
	}

	public String toString(ParametersDelimiter delimiter) {
		Assert.notNull("delimiter", delimiter);
		if (elements.length == 0) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		appendTo(sb, delimiter);
		return sb.toString();
	}

	public void appendTo(StringBuilder sb) {
		Assert.notNull("sb", sb);
		appendTo(sb, getDelimiter());
	}

	public void appendTo(StringBuilder sb, ParametersDelimiter delimiter) {
		Assert.notNull("delimiter", delimiter);
		Assert.notNull("sb", sb);
		sb.append(URLBuilder.QUERY_PREFIX);
		int max = elements.length;
		for (int i = 0; i < max; i++) {
			if (i > 0) {
				sb.append(delimiter.charValue());
			}
			if (elements[i] == ParametersElement.EMPTY) {
				sb.append(delimiter.charValue());
			} else {
				elements[i].appendTo(sb);
			}
		}
	}

	/*
	 * 尚未用到,暂不实现
	 * @see java.lang.Iterable#iterator()
	 */
	@Override
	public Iterator<ParametersElement> iterator() {
		return null;
	}

}
